#include <stdio.h>
#include <gtk/gtk.h>
#include <pthread.h>
#include "ui_task.h"
#include "taskinfo.h"
#include "utils.h"
#include "list.h"
#include "http_manager.h"

typedef struct _taskListContext
{
    GtkWindow *window;
    GtkListStore *task_store;
    GtkTreeView *tree_view;
    GtkTreeSelection *tree_selection;
} TaskListContext;

static TaskListContext *taskListContext;

char *status_arr[N_STATUS]={
    "Ready",
    "Downloading",
    "Finished",
    "Failed",
    "Canceled"
};

int ShowConfirmInfo(GtkWidget *widget, gpointer userdata)
{
    GtkWidget *dialog;
    dialog = gtk_message_dialog_new(GTK_WINDOW(widget),
                                    GTK_DIALOG_DESTROY_WITH_PARENT,
                                    GTK_MESSAGE_QUESTION,
                                    GTK_BUTTONS_OK_CANCEL,
                                    "%s", (char *)userdata);
    gtk_window_set_title(GTK_WINDOW(dialog), "确认信息");
    int result = gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
    
    return result;
    //printf("result :%d, OK:%d\n", result, GTK_RESPONSE_OK);
}

void ShowErrorInfo(GtkWidget *widget, gpointer userdata)
{
    GtkWidget *dialog;
    dialog = gtk_message_dialog_new(GTK_WINDOW(widget),
                                    GTK_DIALOG_DESTROY_WITH_PARENT,
                                    GTK_MESSAGE_ERROR,
                                    GTK_BUTTONS_OK_CANCEL,
                                    "%s", (char *)userdata);
    gtk_window_set_title(GTK_WINDOW(dialog), "错误信息");
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
}

GtkBuilder *OpenUiFile(char *ui_file, GObject **ui_window, int isdestroy)
{
    GError *error = NULL;
    GtkBuilder *builder = gtk_builder_new();

    if (0 == gtk_builder_add_from_file(builder, ui_file, &error))
    {
        g_printerr("加载UI文件失败:%s\n", error->message);
        g_clear_error(&error);
        return NULL;
    }

    GtkWindow *window = (GtkWindow *)gtk_builder_get_object(builder, "window");
    if (isdestroy)
    {
        g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    }

    *ui_window = G_OBJECT(window);

    return builder;
}

void CreateTaskInfo(Taskinfo *taskinfo)
{
    GtkTreeIter iter;

    gtk_list_store_append(taskListContext->task_store, &iter);
    printf("iter:%d\n", iter.stamp);

    char size_str[8] = {0};
    FormatByte(size_str, taskinfo->size);

    gtk_list_store_set(taskListContext->task_store, &iter,
                       COLUMN_FILENAME, taskinfo->filename,
                       COLUMN_SIZE, size_str,
                       COLUMN_PROGRESS, 0.0,
                       COLUMN_STATUS, status_arr[STATUS_READY],
                       COLUMN_ESTIMATE_TIME, "",
                       COLUMN_TRANSFER_RATE, "",
                       COLUMN_CREATE_TIME, taskinfo->create_time,
                       -1);

    GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(taskListContext->task_store), &iter);
    GtkTreeRowReference *row = gtk_tree_row_reference_new(GTK_TREE_MODEL(taskListContext->task_store), path);

    taskinfo->row = row;

    gtk_tree_path_free(path);
}


int updateProcess(HttpContext *context)
{
    GtkTreePath *path = gtk_tree_row_reference_get_path(context->row);
    GtkTreeIter iter;

    gtk_tree_model_get_iter(GTK_TREE_MODEL(taskListContext->task_store), &iter, path);
    gtk_list_store_set(taskListContext->task_store, &iter,
                       COLUMN_PROGRESS, context->progress,
                       COLUMN_ESTIMATE_TIME, context->estimate_time_str,
                       COLUMN_TRANSFER_RATE, context->transfer_rate_str,
                       -1);
    gtk_tree_model_row_changed(GTK_TREE_MODEL(taskListContext->task_store), path,&iter);
    gtk_tree_path_free(path);

    return 0;
}

void removeTask(Taskinfo *taskinfo)
{
    GtkTreePath *path = gtk_tree_row_reference_get_path(taskinfo->row);
    GtkTreeIter iter;

    gtk_tree_model_get_iter(GTK_TREE_MODEL(taskListContext->task_store), &iter, path);
    gtk_list_store_remove(taskListContext->task_store, &iter);

    gtk_tree_path_free(path);
    gtk_tree_row_reference_free(taskinfo->row);

    taskinfo->row = NULL;


}


gboolean OnTaskCreatedFailed(GtkBuilder *builder, const char *msg)
{
    // GtkSpinner *spinner = (GtkSpinner *)gtk_builder_get_object(builder, "ok_spinner");
    // gtk_spinner_stop(spinner);

    GtkWindow *window =  (GtkWindow *)gtk_builder_get_object(builder, "window");

    ShowErrorInfo((GtkWidget *)window, (gpointer)msg);

    return FALSE;
}

void GetTaskInfo(const char *url, GtkBuilder *builder)
{
    HttpContext context = {0};
    sprintf(context.url, "%s", url);
    context.headonly = 1;

    //请求HEADER，拿到Size，文件名
    RequestUrl(&context);

    printf("httpcode:%d\n", context.http_code);

    //成功时创建Taskinfo
    if(context.curl_code != CURLE_OK){
        //出错打印错误信息
        OnTaskCreatedFailed(builder, curl_easy_strerror(context.curl_code));
        return ;
    }

    if(context.http_code >= 400){
        //出错打印错误信息
        char errmsg[8] = {0};
        sprintf(errmsg, "%d", context.http_code);
        OnTaskCreatedFailed(builder, errmsg);
        return ;
    }

    //添加到数据库
    Taskinfo taskinfo = {0};
    sprintf(taskinfo.url, "%s", context.url);
    sprintf(taskinfo.filename, "%s", context.filename);
    taskinfo.size = context.totalsize;
    taskinfo.status = STATUS_READY;

    int ret = InsertTaskInfo(&taskinfo);
    if(ret != RETURN_OK){
        printf("插入数据库失败\n");
        OnTaskCreatedFailed(builder, "插入数据库失败");
        return;
    }


    //显示到界面
    CreateTaskInfo(&taskinfo);

    //添加到链表
    AddItem(&taskinfo);
    
}

void OnConfirmCreateTask(GtkWidget *widget, gpointer userdata)
{
    GtkBuilder *builder = (GtkBuilder *)userdata;

    GtkEntry *entry = (GtkEntry *)gtk_builder_get_object(builder, "url_entry");
    const char *url = gtk_entry_get_text(entry);

    GtkSpinner *spinner = (GtkSpinner *)gtk_builder_get_object(builder, "ok_spinner");
    gtk_spinner_start(spinner);


    printf("url :%s\n", url);

    GetTaskInfo(url, builder);

    GtkWindow *window =  (GtkWindow *)gtk_builder_get_object(builder, "window");
    gtk_dialog_response(GTK_DIALOG(window), 1);
}

void OpenNewTaskWindow(GtkWidget *widget, gpointer userdata)
{
    GObject *window;
    GtkBuilder *builder = OpenUiFile("new_task.ui", &window, 0);
    if (!builder)
    {
        printf("打开新建窗口失败\n");
    }

    GObject *ok = NULL, *cancel = NULL;
    ok = gtk_builder_get_object(builder, "ok_button");

    g_signal_connect(ok, "clicked", G_CALLBACK(OnConfirmCreateTask), builder);

    cancel = gtk_builder_get_object(builder, "cancel_button");

    int result = gtk_dialog_run(GTK_DIALOG(window));

    printf("打开成功 result:%d\n", result);

    gtk_widget_destroy(GTK_WIDGET(window));
}

void InitTaskList(GtkBuilder *builder)
{
    if (taskListContext == NULL)
    {
        taskListContext = calloc(1, sizeof(TaskListContext));
        taskListContext->window = (GtkWindow *)gtk_builder_get_object(builder, "window");

        taskListContext->task_store = (GtkListStore *)gtk_builder_get_object(builder, "task_store");
        taskListContext->tree_view = (GtkTreeView *)gtk_builder_get_object(builder, "task_tree");
        taskListContext->tree_selection = (GtkTreeSelection *)gtk_builder_get_object(builder, "task_selection");
    }

    //遍历链表将内容添加到界面
    Traverse(CreateTaskInfo);
}


static int getSelectedTaskIndex(char *filename)
{
    GtkTreeIter iter;
    GtkTreeModel *model;
    gchar *title;

    if(gtk_tree_selection_get_selected(taskListContext->tree_selection, &model, &iter)){
        gtk_tree_model_get(model, &iter, COLUMN_FILENAME, &title, -1);
        printf("select file:%s\n", title);
        sprintf(filename, "%s", title);
        g_free(title);
        return RETURN_OK;
    }

    return RETURN_FAILED;
}
void StartDownladTask(GtkWidget *widget, gpointer userdata)
{
    char filename[FILENAME_LEN] = {0};
    int ret = 0;

    //从界面找到选中的index
    ret = getSelectedTaskIndex(filename);
    if(ret != RETURN_OK){
        printf("未选中Task\n");
        ShowErrorInfo((GtkWidget *)taskListContext->window, "未选中Task!");
        return ;
    }

    //从链表拿到taskinfo
    Taskinfo taskinfo = {0};
    GetTaskinfoByFilename(&taskinfo, filename);

    //开始下载并更新进度
    HttpContext *context = calloc(1, sizeof(HttpContext));
    context->row = taskinfo.row;
    sprintf(context->url, "%s", taskinfo.url);
    context->headonly = 0;
    
    //请求HEADER，拿到Size，文件名
    pthread_t tid;
    pthread_create(&tid, NULL, RequestUrl, context);
    pthread_detach(tid);
    //pthread_join(tid, NULL);
}


void RemoveSlectedTask(GtkWidget *widget, gpointer userdata)
{
    //弹窗确认
    if(GTK_RESPONSE_OK != ShowConfirmInfo((GtkWidget *)taskListContext->window, "确认要删除吗？")){
        return ;
    }

    //删除链表内容
    char filename[FILENAME_LEN] = {0};
    int ret = 0;

    //从界面找到选中的index
    ret = getSelectedTaskIndex(filename);
    if(ret != RETURN_OK){
        printf("未选中Task\n");
        ShowErrorInfo((GtkWidget *)taskListContext->window, "未选中Task!");
        return ;
    }

    //从链表拿到taskinfo
    Taskinfo taskinfo = {0};
    GetTaskinfoByFilename(&taskinfo, filename);

    //停止当前下载
    CancelDownloadFile();

    //删除链表的内容
    RemoveListItem(&taskinfo);

    //删除数据库内容
    DeleteTaskInfo(&taskinfo);

    //界面删除
    removeTask(&taskinfo);

}

void StopDownloadingTask(GtkWidget *widget, gpointer userdata)
{
    CancelDownloadFile();
}

void FreeTaskList(void)
{
    if (taskListContext)
    {
        free(taskListContext);
        taskListContext = NULL;
    }
}
